﻿using Microsoft.EntityFrameworkCore;
using MyAppAPI.Context;
using MyAppAPI.Models.Hotel;
using MyAppAPI.ParamModel;
using MyAppAPI.Repositories.interfaceRepo;
using MyAppAPI.Services.interfaceService;
using System.Collections.Generic;
using System.Linq;

namespace MyAppAPI.Repositories
{
    public class HotelRepository:IHotelRepository
    {
        private readonly UserContext userContext;
        public HotelRepository(UserContext _userInfoContext) 
        {
            userContext= _userInfoContext;
        }
        public async Task<UserData> Login(string loginId, string loginPwd)
        {
            var user=await userContext.UserDatas.Where(o => o.loginId == loginId && o.loginPwd == loginPwd).FirstOrDefaultAsync();
            return user;
        }
        public async Task<bool> AddRoleName(string roleName)
        {
             await userContext.RoleDatas.AddAsync(new RoleData() { RoleName=roleName});
            return userContext.SaveChanges() > 0;
        }

        public async Task<List<RoleData>> GetAllRoleType()
        {
            var list=await userContext.RoleDatas.ToListAsync();
            return list;
        }
        public async Task<bool> DeleteRoleName(int roleId)
        {
            RoleData roleData=await userContext.RoleDatas.Where(o=>o.RoleId==roleId).FirstAsync();
            userContext.RoleDatas.Remove(roleData);
            return userContext.SaveChanges()>0;
        }
        public async Task<RoleData> GetRoleByRoleId(int roleId)
        {
            return await userContext.RoleDatas.Where<RoleData>(o=>o.RoleId==roleId).FirstAsync();
        }
        public bool UpdateRoleByRoleId(RoleData roleData)
        {
            userContext.RoleDatas.Update(roleData);
            return userContext.SaveChanges() > 0;
        }
        public List<UserData> GetAllUser(ref int count, int pageIndex, int pageSize)
        {
            count=userContext.UserDatas.Count();
            return userContext.UserDatas.Skip((pageIndex-1)*pageSize).Take(pageSize).ToList();
        }
        public List<UserData> GetAllUserByRoleId(int roleId, ref int count, int pageIndex, int pageSize)
        {
            count = userContext.UserDatas.Count(o=>o.roleId==roleId);
            return userContext.UserDatas.Where(o=>o.roleId==roleId).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
        }
        public async Task<UserData> GetUser(string loginId)
        {
            return await userContext.UserDatas.Where(o => o.loginId == loginId).FirstAsync();
        }
        public async Task<bool> AddUser(UserData userData)
        {

             await userContext.UserDatas.AddAsync(userData);
            return userContext.SaveChanges()>0;
        }
        public bool UpdateUser(UserData userData)
        {
            userContext.UserDatas.Update(userData);
            return userContext.SaveChanges() > 0;
        }
        public async Task<bool> DeleteUser(int id)
        {
            var user =await userContext.UserDatas.Where(o=>o.id==id).FirstAsync();
            userContext.UserDatas.Remove(user);
            return userContext.SaveChanges() > 0;
        }
        public async Task<bool> ResetPwd(ResetPwdParams resetPwdParams)
        {
            var user =await userContext.UserDatas.Where(o => o.id == resetPwdParams.id).FirstAsync();
            if (user.loginPwd != resetPwdParams.oldLoginPwd)
            {
                return false;
            }
            user.loginPwd = resetPwdParams.newLoginPwd;
            userContext.UserDatas.Update(user);
            return userContext.SaveChanges() > 0;
        }
        public async Task<List<RoomTypeData>> GetAllRoomType()
        {
            return await userContext.RoomTypeDatas.ToListAsync();
        }
        public async Task<bool> AddRoomType(RoomTypeData roomTypeData)
        {
            await userContext.RoomTypeDatas.AddAsync(roomTypeData);
            return userContext.SaveChanges()>0;
        }
        public async Task<RoomTypeData> GetRoomTypeByRoomTypeId(int roomTypeId)
        {
            return await userContext.RoomTypeDatas.Where<RoomTypeData>(o => o.RoomTypeId == roomTypeId).FirstAsync();
        }
        public bool UpdateRoomByRoomTypeId(RoomTypeData roomTypeData)
        {
            userContext.RoomTypeDatas.Update(roomTypeData);
            return userContext.SaveChanges()>0;
        }
        public async Task<bool> DeleteRoomType(int roomTypeId)
        {
            var roomType=await userContext.RoomTypeDatas.Where(o => o.RoomTypeId == roomTypeId).FirstAsync();
            userContext.RoomTypeDatas.Remove(roomType);
            return userContext.SaveChanges()>0;
        }
        public List<RoomData> GetAllRoom(int roomTypeId,int roomStateId, int guestId)
        {
            IQueryable<RoomData> queryData= userContext.roomDatas;
            if (roomTypeId > 0)
            {
                queryData = queryData.Where(o => o.roomTypeId == roomTypeId);
            }
            if(roomStateId>0)
            {
                queryData = queryData.Where(o => o.roomStateId == roomStateId);
            }
            var roomList = queryData.ToList();
            if(guestId>0)
            {
                var guest=userContext.guestDatas.Where(o => o.guestId == guestId).First();
                var room=userContext.roomDatas.Where(o => o.roomId == guest.roomId).First();
                if(room.roomTypeId==roomTypeId&&!(roomList.Select(o=>o.roomId).Contains(guestId)))
                {
                    roomList.Add(room);
                }
            }
            return roomList;
        }
        public List<RoomStateData> GetAllRoomState(int flag)
        {
            if(flag==0)
            {
                return userContext.roomStateDatas.ToList();
            }
            return userContext.roomStateDatas.Where(o => o.roomStateId != 2).ToList();
            
        }
        public async Task<bool> AddRoom(RoomData roomData)
        {
            await userContext.roomDatas.AddAsync(roomData);
            return userContext.SaveChanges()>0;
        }
        public async Task<RoomData> GetRoomByRoomId(int roomId)
        {
            return await userContext.roomDatas.Where(o => o.roomId == roomId).FirstAsync();
        }
        public bool UpdateRoomData(RoomData roomData)
        {
            userContext.roomDatas.Update(roomData);
            return userContext.SaveChanges() > 0;
        }
        public bool DeleteRoomData(int roomId)
        {
            var roomData=userContext.roomDatas.Where(o=>o.roomId == roomId).First();
            userContext.roomDatas.Remove(roomData);
            return userContext.SaveChanges() > 0;
        }
        public List<GuestData> GetAllGuest(string guestName, int resideStateId)
        {
            var queryableGuest = userContext.guestDatas.Where(o=>true);
            if(!string.IsNullOrEmpty(guestName))
            {
                queryableGuest = queryableGuest.Where(o => o.guestName == guestName);
            }
            if(resideStateId>0)
            {
                queryableGuest = queryableGuest.Where(o => o.resideStateId == resideStateId);
            }
            return queryableGuest.ToList();
        }
        public List<ResideState> GetAllResideStateData()
        {
            return userContext.resideStates.ToList();
        }
        public ResideState GetResideSatetByStateId(int resideStateId)
        {
            return userContext.resideStates.Where(o=>o.resideStateId==resideStateId).First();
        }
        public bool AddGuestRecord(GuestData guestData)
        {
            userContext.guestDatas.Add(guestData);
            var guest=userContext.roomDatas.Where(o => o.roomId == guestData.roomId).First();
            guest.roomStateId = 2;
            userContext.roomDatas.Update(guest);
            return userContext.SaveChanges() > 0;
        }
        public GuestData GetGuestDataByGuestId(int guestId)
        {
            return userContext.guestDatas.Where(o => o.guestId == guestId).First();
        }
        public bool UpdateGuestData(GuestData guestData)
        {
            var oldGuestData = userContext.guestDatas.AsNoTracking().Where(o => o.guestId == guestData.guestId).First();
            var oldRoomData=userContext.roomDatas.AsNoTracking().Where(o => o.roomId == oldGuestData.roomId).First();
            
            oldRoomData.roomStateId = 1;

            userContext.guestDatas.Update(guestData);
            if(guestData.roomId!=oldGuestData.roomId)
            {
                userContext.roomDatas.Update(oldRoomData);
                var newRoomData = userContext.roomDatas.Where(o => o.roomId == guestData.roomId).First();
                newRoomData.roomStateId= 2;
                userContext.roomDatas.Update(newRoomData);
            }
            
            
            return userContext.SaveChanges() > 0;
        }
        public bool DeleteGuestDataByGuestId(int guestId)
        {
            var guest=userContext.guestDatas.Where(o => o.guestId == guestId).First();
            userContext.guestDatas.Remove(guest);
            return userContext.SaveChanges() > 0;
        }
        public GuestData Checkout(int guestId)
        {
            GuestData guestData = new();
            var guest=userContext.guestDatas.Where(o => o.guestId == guestId).First();
            var now = DateTime.Now;
            guest.leaveDate = now.ToString("yyyy/MM/dd HH:mm:ss");
            var room = userContext.roomDatas.Where(o => o.roomId == guest.roomId).First();
            var roomType = userContext.RoomTypeDatas.Where(o => o.RoomTypeId == room.roomTypeId).First();
            var dayCount = (now - DateTime.Parse(guest.resideDate)).Hours>1? ((now - DateTime.Parse(guest.resideDate)).Days<1?1: (now - DateTime.Parse(guest.resideDate)).Days) :0;
            guest.totalMoney=roomType.RoomTypePrice * dayCount;
            guest.resideStateId = 2;
            guestData = guest;
            //更新roomdata
            room.roomStateId = 1;
            userContext.SaveChanges();
            return guestData;
        }
        public List<RoomTypeTotalData> GetRoomTypeTotalMoney()
        {
            var roomtype = userContext.RoomTypeDatas.ToList();
            var roomData=userContext.roomDatas.ToList();
            var guest = userContext.guestDatas.ToList();
            List<RoomTypeTotalData> roomList = new();
            foreach (var item in roomtype)
            {
                RoomTypeTotalData roomTypeTotalData = new();
                roomTypeTotalData.roomtypeName = item.RoomTypeName;
                decimal total = 0;
                if(roomData.Select(o=>o.roomTypeId).Contains(item.RoomTypeId))
                {
                    foreach (var rd in roomData.Where(o=>o.roomTypeId==item.RoomTypeId))
                    {
                        if(guest.Where(o=>o.resideStateId==2&&o.roomId==rd.roomId).Any())
                        {
                            total += guest.Where(o => o.resideStateId == 2 && o.roomId == rd.roomId).First().totalMoney;
                        }
                        else
                        {
                            total += 0;
                        }
                    }
                }
                else
                {
                    total += 0;
                }
                roomTypeTotalData.totalMoney= total;
                roomList.Add(roomTypeTotalData);
            }
            return roomList;
        }
    }
}
